----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    02:20:45 10/01/2009 
-- Design Name: 
-- Module Name:    program_tx - arch 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity program_tx is
    Port ( data_in : in  STD_LOGIC_VECTOR (127 downto 0);
           clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           w_data : out  STD_LOGIC_VECTOR (7 downto 0);
           tx_full : in  STD_LOGIC;
           wr_uart : out  STD_LOGIC;
           data_available : in  STD_LOGIC;
			  data_ack : out STD_LOGIC);
end program_tx;

architecture arch of program_tx is

type statetype is ( S1, S2, S3, S4, S5  );
signal state, next_state : statetype := S1;

signal data_buffer_store : std_logic_vector(127 downto 0);
signal data_buffer : std_logic_vector(127 downto 0);
signal checksum : std_logic_vector(7 downto 0);

signal line_counter: std_logic_vector (5 downto 0) := (others=>'0');

begin


state <= next_state;

process (clk, reset) is
begin
		 if (reset = '1') then
					next_state <= S1;
					line_counter <= (others=>'0');
					
		 elsif (rising_edge(clk)) then
					case state is

					when S1 => 
					
						wr_uart <= '0';
						w_data <= (others=>'0');
						if (data_available = '0') then
							next_state <= S1;
						else
							next_state <= S2;
							data_ack <= '1';
						end if;
					
					when S2 =>
						
						data_ack <='0';
						data_buffer_store <= data_in;
						data_buffer <= data_in;
						line_counter <= (others=> '0');
						checksum <= (others=> '0');
						if (data_available = '1') then
							next_state <= S2;
						else
							next_state <= S3;
						end if;

					when S3 =>
						-- Calculate the checksum
						if (line_counter = "010000") then
							next_state <= S4;
							line_counter <= (others=> '0');
							data_buffer <= data_buffer_store;
						else
							checksum <= checksum + data_buffer(127 downto 120);
							data_buffer <= data_buffer(119 downto 0) & "00000000";
							line_counter <= line_counter + 1;
							next_state <= S3;
						end if;
					
					when S4 =>
					
						if (tx_full = '0') then
							wr_uart <= '1';
							if (line_counter = "000000") then
								w_data <= x"00";
								-- Test for position 1 to 3
								next_state <= S5;
							elsif (line_counter(5 downto 1) = "0001" or line_counter = "000001") then
								w_data <= x"00";
								next_state <= S5;
							elsif (line_counter = "010100") then -- Checksum
								w_data <= checksum;
								next_state <= S5;
							elsif (line_counter = "010101") then -- Trailer
								w_data <= (others => '1');
								next_state <= S5;
							else
								if (line_counter /= "010011") then
									w_data <= data_buffer(127 downto 120);
									data_buffer <= data_buffer(119 downto 0) & "00000000";
									next_state <= S5;
								else
									next_state <= S1;
								end if;
							end if;
							line_counter <= line_counter + 1;
						else
							next_state <= S4;
						end if;

					when S5 =>
						wr_uart <= '0';
						next_state <= S4;
					
					end case;

		 end if;
	end process;
	
	
end arch;

